package cn.singlewindow.ha.util.collector.integration.component;

import cn.singlewindow.ha.util.collector.config.AppParameters;
import cn.singlewindow.ha.util.collector.integration.constant.ChannelConstant;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.expression.Expression;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.integration.annotation.*;
import org.springframework.integration.core.MessageSource;
import org.springframework.integration.file.FileReadingMessageSource;
import org.springframework.integration.file.FileWritingMessageHandler;
import org.springframework.integration.file.filters.FileListFilter;
import org.springframework.integration.file.support.FileExistsMode;
import org.springframework.integration.file.transformer.FileToByteArrayTransformer;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageHandler;
import org.springframework.util.StringUtils;

import java.io.File;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 1 从目录读取xml,xlsx,xls,html文件
 * 2 备份文件到backup/send|rece/日期目录
 * 3 开始处理，不同类型文件做不同处理，分为 xml|excel|html|other其他
 * 4
 */

@Configuration
public class IntegrationComponent {

    @Autowired
    private AppParameters appParameters;

    @Bean
    public ExecutorService executorService() {
        return Executors.newFixedThreadPool(appParameters.getThreadPool());
    }

//    @Autowired
//    IParserService iParserService;

    @Bean
    @InboundChannelAdapter(value = ChannelConstant.CHANNEL_RECEDIR, poller = @Poller(fixedDelay = "${app.file.fixedDelay}", maxMessagesPerPoll = "${app.file.maxMessagesPerPoll}"))
    public MessageSource<File> fileReadingMessageSource() {
        FileReadingMessageSource source = new FileReadingMessageSource();
        source.setDirectory(new File(appParameters.getRecedir()));
        source.setAutoCreateDirectory(true);
        source.setFilter(fileListFilter());
//        source.setFilter(new AcceptAllFileListFilter());
        return source;
    }

    private FileListFilter fileListFilter(){
        return (FileListFilter<File>) files -> {
            List<File> list = new ArrayList<>();
            for(File file:files){
                if(file.isDirectory()){
                    continue;
                }
                if(file.getAbsolutePath().endsWith(".html")||file.getAbsolutePath().endsWith(".xlsx")||file.getAbsolutePath().endsWith(".xml")||file.getAbsolutePath().endsWith(".xls")){
                    list.add(file);
                }
            }
            return list;
        };
//        return new FileListFilter<File>() {
//            @Override
//            public List<File> filterFiles(File[] files) {
//                List<File> list = new ArrayList<>();
//                for(File file:files){
//                    if(file.getAbsolutePath().endsWith(".html")||file.getAbsolutePath().endsWith(".xlsx")||file.getAbsolutePath().endsWith(".xml")||file.getAbsolutePath().endsWith(".xls")){
//                        list.add(file);
//                    }
//                }
//                return list;
//            }
//        };
    }

    @Bean
    @Transformer(inputChannel = ChannelConstant.CHANNEL_RECEDIR,outputChannel = ChannelConstant.CHANNEL_BYTE)
    public FileToByteArrayTransformer fileToByteArrayTransformer(){
        FileToByteArrayTransformer transformer = new FileToByteArrayTransformer();
        transformer.setDeleteFiles(true);
        return transformer;
    }

    @Bean
    @ServiceActivator(inputChannel = ChannelConstant.CHANNEL_BACKUPDIR_RECE)
    public MessageHandler receBackupMessageHandler() {
        return baseMessageHandler(appParameters.getBackupdir()+File.separator+"rece","FILE_BACKUP");

    }

    @Bean
    @ServiceActivator(inputChannel = ChannelConstant.CHANNEL_BACKUPDIR_SEND)
    public MessageHandler sendBackupMessageHandler() {
        return baseMessageHandler(appParameters.getBackupdir()+File.separator+"send","FILE_BACKUP");

    }

    @Bean
    @ServiceActivator(inputChannel = ChannelConstant.CHANNEL_ERRORDIR_RECE)
    public MessageHandler receBackupErrorMessageHandler() {
        return baseMessageHandler(appParameters.getBackupdir()+File.separator+"rece","error"+File.separator+"FILE_BACKUP");

    }

    @Bean
    @ServiceActivator(inputChannel = ChannelConstant.CHANNEL_ERRORDIR_SEND)
    public MessageHandler sendBackupErrorMessageHandler() {
        return baseMessageHandler(appParameters.getBackupdir()+File.separator+"send","error"+File.separator+"FILE_BACKUP");
    }

    @ServiceActivator(inputChannel = ChannelConstant.CHANNEL_BYTE)
    public void thirdMessageHandler(Message message) {
        executorService().execute(new HandlerModel(message));
    }

    private String backupDayDirGenerator(){
        String backupDirFormat = "yyyyMMdd".equals(appParameters.getBackupDateFormat())?appParameters.getBackupDateFormat():"yyyyMMddHH";
        backupDirFormat = new SimpleDateFormat(backupDirFormat).format(new Date());
        return backupDirFormat;
    }

    private MessageHandler baseMessageHandler(String dir, String prefix){
        Expression directoryExpression = new SpelExpressionParser().parseExpression("@filePara.getTodayDir('" + dir + "')");
        FileWritingMessageHandler handler = new FileWritingMessageHandler(directoryExpression);
        handler.setAutoCreateDirectory(true);
        handler.setExpectReply(false);
        handler.setFileExistsMode(FileExistsMode.FAIL);
        handler.setFileNameGenerator(new AppFileNameGenerator(prefix,null,null));
        return handler;
    }


    @Bean
    public Object filePara() {
        return new Object() {
            public String getTodayDir(String dir) {
                return !StringUtils.hasLength(dir) ? "" : dir + File.separator + backupDayDirGenerator();
            }
        };
    }

    @MessagingGateway(defaultRequestChannel = ChannelConstant.CHANNEL_BACKUPDIR)
    public interface MyGateway {

        @Gateway(requestChannel = ChannelConstant.CHANNEL_SENDDIR)
        void sendMessage(Message message);

        @Gateway(requestChannel = ChannelConstant.CHANNEL_ERRORDIR_SEND)
        void errorSend(Message message);

        @Gateway(requestChannel = ChannelConstant.CHANNEL_ERRORDIR_RECE)
        void errorRece(Message message);

        @Gateway(requestChannel = ChannelConstant.CHANNEL_BACKUPDIR_SEND)
        void backupSend(Message message);

        @Gateway(requestChannel = ChannelConstant.CHANNEL_BACKUPDIR_RECE)
        void backupRece(Message message);

        void backupMessage(Message message);
    }
}
